package cn.caishen.report.service.report.impl;

import cn.caishen.report.common.constant.LbConstant;
import cn.caishen.report.common.exceptions.BusinessException;
import cn.caishen.report.common.utils.*;
import cn.caishen.report.dao.report.ReportConfigDao;
import cn.caishen.report.domain.report.*;
import cn.caishen.report.service.report.*;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


@Service("reportConfigService")
@Transactional(rollbackFor = Throwable.class)
@Slf4j
public class ReportConfigServiceImpl extends ServiceImpl<ReportConfigDao, ReportConfig> implements ReportConfigService {

    private final ReportFieldService reportFieldService;
    private final ReportWhereService reportWhereService;
    private final ReportConfigDao reportConfigDao;
    private final ReportUserFieldService reportUserFieldService;
    private final ReportChartService reportChartService;
    private final ReportChartWhereService reportChartWhereService;

    public ReportConfigServiceImpl(ReportFieldService reportFieldService, ReportWhereService reportWhereService, ReportConfigDao reportConfigDao,
                                   ReportUserFieldService reportUserFieldService, ReportChartService reportChartService,
                                   ReportChartWhereService reportChartWhereService) {
        this.reportFieldService = reportFieldService;
        this.reportWhereService = reportWhereService;
        this.reportConfigDao = reportConfigDao;
        this.reportUserFieldService = reportUserFieldService;
        this.reportChartService = reportChartService;
        this.reportChartWhereService = reportChartWhereService;
    }

    /**
     * 通过配置获取报表列表
     *
     * @param moduleId
     * @param detailReportConfigId
     * @return
     */
    @Override
    @SneakyThrows
    public LbMap getModuleReport(Integer moduleId, Integer detailReportConfigId) {
        ReportConfig reportConfig = null;
        if (moduleId > 0) {
            reportConfig = getReportConfig(moduleId);
        } else if (detailReportConfigId > 0) {
            reportConfig = this.getById(detailReportConfigId);
        }

        if (Objects.isNull(reportConfig)) {
            throw new BusinessException("未找到报表配置");
        }

        int reportConfigId = reportConfig.getReportConfigId();
        //UserVo user = LoginInformation.getUser();

        //查询配置字段
        /*QueryWrapper<ReportField> fieldWrapper = new QueryWrapper<>();
        fieldWrapper.eq("report_config_id", reportConfigId).eq("on_show", LbConstant.ON_SHOW.SHOW.getCode()).orderByAsc("order_by");
        List<ReportField> titleList = reportFieldService.list(fieldWrapper);

        //查询条件
        QueryWrapper<ReportWhere> whereWrapper = new QueryWrapper<>();
        whereWrapper.eq("report_config_id", reportConfigId).eq("on_show", LbConstant.ON_SHOW.SHOW.getCode()).orderByAsc("order_by");
        List<ReportWhere> whereParamList = reportWhereService.list(whereWrapper);

        //用户显示列标题
        QueryWrapper<ReportUserField> userFieldWrapper = new QueryWrapper<>();
        userFieldWrapper.eq("report_config_id", reportConfigId).eq("user_id", 0).orderByAsc("order_by");
        List<ReportUserField> reportUserFieldList = reportUserFieldService.list(userFieldWrapper);*/

        ReportConfig reportInfo = getReportInfo(reportConfigId, true);
        List<ReportWhere> whereParamList = reportInfo.getReportWhereList();
        List<ReportField> titleList = reportInfo.getReportFieldList();

        LbMap map = new LbMap();

        for (ReportWhere reportWhere : whereParamList) {
            if (reportWhere.getParamType().equals(LbConstant.PARAM_TYPE.SELECT.getName())) {
                if (StringUtil.isEmpty(reportWhere.getTableName())) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 select 时，表名称不能为空");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                if (StringUtil.isEmpty(reportWhere.getLinkJson())) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 select 时，关联json不能为空");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                Map<String, String> keyMap = new HashMap<>();
                try {
                    keyMap = JSONObject.parseObject(reportWhere.getLinkJson(), Map.class);
                } catch (Exception e) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 select 时，关联json解析不成功");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                String key = "";
                String value = "";

                if (Objects.isNull(keyMap)) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 select 时，关联json解析为空");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                for (Map.Entry<String, String> entry : keyMap.entrySet()) {
                    key = entry.getKey();
                    value = entry.getValue();

                    if (StringUtil.isNotEmpty(key) && StringUtil.isNotEmpty(value)) {
                        break;
                    }
                }

                //select 类型的字段，需要把下拉的值返回，以 [{"id":1, "name":张三}] 的json 格式返回
                List<LbMap> selectList = reportConfigDao.getSelectList(reportWhere.getTableName(), 0, key, value);
                map.put(reportWhere.getParamName(), selectList);
            } else if (reportWhere.getParamType().equals(LbConstant.PARAM_TYPE.LIST.getName())) {
                if (StringUtil.isEmpty(reportWhere.getLinkJson())) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 list 时，关联json不能为空");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                List<LbMap> selectList = new ArrayList<>();
                try {
                    selectList = JSONObject.parseObject(reportWhere.getLinkJson(), List.class);
                } catch (Exception e) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 list 时，关联json解析不成功");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }
                map.put(reportWhere.getParamName(), selectList);
            }
        }

        List<ReportUserField> reportUserFieldList = reportInfo.getReportUserFieldList();
        List<ReportField> newReportFieldList = new ArrayList<>();
        if (reportUserFieldList.size() > 0) {
            //循环表头
            for (ReportField reportField : titleList) {
                ReportUserField reportUserField = new ReportUserField();
                reportUserField.setReportConfigId(reportField.getReportConfigId());
                reportUserField.setUserId(0);
                reportUserField.setFieldName(reportField.getFieldName());

                //如果在用户配置字段里包含该表头，则将用户设置的长度进行赋值
                if (reportUserFieldList.contains(reportUserField)) {
                    ReportUserField newReportUserField = reportUserFieldList.get(reportUserFieldList.indexOf(reportUserField));
                    reportField.setFieldWidth(newReportUserField.getFieldWidth());
                    newReportFieldList.add(reportField);
                }
            }
        } else {
            newReportFieldList.addAll(titleList);
        }

        //处理返回的结果，隐藏SQL语句
        LbMap reportConfigMap = new LbMap();
        reportConfigMap.put("reportName", reportConfig.getReportName());
        reportConfigMap.put("moduleName", reportConfig.getModuleName());
        reportConfigMap.put("needChart", reportConfig.getNeedChart());

        List<LbMap> whereList = new ArrayList<>();

        //处理汇总对象
        LbMap reportAxisMap = getReportAxis(moduleId);
        List<LbMap> xList = reportAxisMap.getList("xList");
        if (xList.size() > 0) {
            String groupFields = "groupFields";
            //增加一个条件，汇总对象，将所有标记为 x 轴的列做为汇总对象
            LbMap whereMap = new LbMap();
            whereMap.put("paramName", groupFields);
            whereMap.put("paramType", "list");
            whereMap.put("fieldName", groupFields);
            whereMap.put("fieldCnName", "汇总对象");
            whereMap.put("defaultValue", null);
            whereList.add(whereMap);

            List<LbMap> newXList = new ArrayList<>();
            for (LbMap xMap : xList) {
                LbMap newXMap = new LbMap();
                String fieldName = xMap.getString("fieldName");
                String fieldCnName = xMap.getString("fieldCnName");
                newXMap.put("id", fieldName);
                newXMap.put("name", fieldCnName);
                newXList.add(newXMap);
            }
            map.put(groupFields, newXList);
        }

        for (ReportWhere reportWhere : whereParamList) {
            LbMap whereMap = new LbMap();
            whereMap.put("reportWhereId", reportWhere.getReportWhereId());
            whereMap.put("paramName", reportWhere.getParamName());
            whereMap.put("paramType", reportWhere.getParamType());
            whereMap.put("fieldName", reportWhere.getFieldName());
            whereMap.put("fieldCnName", reportWhere.getFieldCnName());
            whereMap.put("defaultValue", reportWhere.getDefaultValue());
            //whereMap.put("dateType", reportWhere.getDateType());
            whereList.add(whereMap);
        }

        map.put(LbConstant.REPORT_CONFIG, reportConfigMap);
        map.put(LbConstant.TITLE_LIST, titleList);
        map.put(LbConstant.WHERE_PARAM_LIST, whereList);
        map.put(LbConstant.REPORT_USER_FIELD_LIST, newReportFieldList);

        return map;
    }

    /**
     * 分页查询动态报表
     *
     * @param param
     * @param moduleId
     * @param detailReportConfigId
     * @param page
     * @param limit
     * @param needSum
     * @param selectFields
     * @param orderFields
     * @param groupFields
     * @param lastSql
     * @return
     */
    @Override
    @SneakyThrows
    public LbMap getReportList(LbMap param, int moduleId, int detailReportConfigId, int page, int limit,
                               boolean needSum, String selectFields, String orderFields, String groupFields, String lastSql) {
        ReportConfig reportConfig = null;
        if (moduleId > 0) {
            reportConfig = getReportConfig(moduleId);
        } else if (detailReportConfigId > 0) {
            reportConfig = this.getById(detailReportConfigId);
        }

        if (Objects.isNull(reportConfig)) {
            throw new BusinessException("未找到报表配置");
        }

        String selectSql = reportConfig.getSelectSql();
        if (StringUtil.isEmpty(selectSql)) {
            throw new BusinessException("设置的查询语句不能为空");
        }

        String fromSql = reportConfig.getFromSql();
        if (StringUtil.isEmpty(fromSql)) {
            throw new BusinessException("设置的来源语句不能为空");
        }

        //UserVo user = LoginInformation.getUser();

        //转换unitId
        fromSql = fromSql.replace(getParamName(), 0 + "");

        //groupBy orderBy 这两个可以为空，所以不进行检查
        String groupBySql = reportConfig.getGroupBySql();
        String orderBySql = reportConfig.getOrderBySql();

        //处理排序字段
        if (StringUtil.isNotEmpty(orderFields)) {
            orderFields = orderFields.replace("#", " ");
            orderBySql = orderFields;
        }

        String whereSql = reportConfig.getWhereSql();

        if (StringUtil.isEmpty(whereSql)) {
            whereSql = "";
        }

        //转换unitId
        whereSql = whereSql.replace(getParamName(), 0 + "");

        int reportConfigId = reportConfig.getReportConfigId();
        /*QueryWrapper<ReportWhere> whereWrapper = new QueryWrapper<>();
        whereWrapper.eq("report_config_id", reportConfigId).orderByAsc("order_by");
        List<ReportWhere> whereParamList = reportWhereService.list(whereWrapper);*/

        ReportConfig reportInfo = getReportInfo(reportConfigId, false);
        List<ReportWhere> whereParamList = reportInfo.getReportWhereList();
        List<ReportField> titleList = reportInfo.getReportFieldList();
        List<ReportUserField> reportUserFieldList = reportInfo.getReportUserFieldList();

        for (ReportWhere reportWhere : whereParamList) {
            //数据库字段
            String fieldName = reportWhere.getFieldName();
            //前端显示参数
            String paramName = reportWhere.getParamName();
            //参数类型
            String paramType = reportWhere.getParamType();
            if (LbConstant.PARAM_TYPE.DATE.getName().equals(paramType) || LbConstant.PARAM_TYPE.TIME.getName().equals(paramType)) {
                //日期类型单独处理
                String[] dates = paramName.split(",");

                String format = "yyyy-MM-dd";
                if (LbConstant.PARAM_TYPE.TIME.getName().equals(paramType)) {
                    format = "yyyy-MM-dd HH:mm:ss";
                }

                if (dates.length == 2) {
                    //带开始日期，结束日期类型的
                    String startDate = dates[0];
                    String endDate = dates[1];

                    String startValue = param.getString(startDate);
                    String endValue = param.getString(endDate);

                    if (StringUtil.isNotEmpty(startValue)) {
                        String startDateStr = DateUtil.getDateStrFromISO8601Timestamp(startValue, format);
                        whereSql = StringUtil.StringAdd(whereSql, getCompare(LbConstant.COMPARE.GE.getCode(), fieldName, startDateStr), " and ");
                    }

                    if (StringUtil.isNotEmpty(endValue)) {
                        String endDateStr = DateUtil.getDateStrFromISO8601Timestamp(endValue, format);
                        whereSql = StringUtil.StringAdd(whereSql, getCompare(LbConstant.COMPARE.LE.getCode(), fieldName, endDateStr), " and ");
                    }
                } else {
                    //只有一个日期时，按配置的比较值进行拼接
                    String paramValue = DateUtil.getDateStrFromISO8601Timestamp(param.getString(paramName), format);
                    int compare = reportWhere.getCompare();
                    if (StringUtil.isNotEmpty(paramValue)) {
                        whereSql = StringUtil.StringAdd(whereSql, getCompare(compare, fieldName, paramValue), " and ");
                    }
                }
            } else {
                //参数值
                String paramValue = param.getString(paramName);
                int compare = reportWhere.getCompare();

                if (StringUtil.isNotEmpty(paramValue)) {
                    //拼接语句
                    if (paramValue.contains(",")) {
                        whereSql = StringUtil.StringAdd(whereSql, getCompare(LbConstant.COMPARE.IN.getCode(), fieldName, paramValue), " and ");
                    } else {
                        whereSql = StringUtil.StringAdd(whereSql, getCompare(compare, fieldName, paramValue), " and ");
                    }
                }
            }
        }

        //将表头再返回给前端
        /*QueryWrapper<ReportField> fieldWrapper = new QueryWrapper<>();
        fieldWrapper.eq("report_config_id", reportConfigId).eq("on_show", LbConstant.ON_SHOW.SHOW.getCode()).orderByAsc("order_by");
        List<ReportField> titleList = reportFieldService.list(fieldWrapper);*/

        //查询用户自定义列
        /*List<ReportUserField> reportUserFieldList = reportUserFieldService.list(new QueryWrapper<ReportUserField>().eq("unit_id", 0)
                .eq("user_id", 0).eq("report_config_id", reportConfig.getReportConfigId()).orderByAsc("order_by"));*/

        //处理显示字段
        String newSelectFields = "";
        List<ReportField> newReportFieldList = new ArrayList<>();
        if (StringUtil.isNotEmpty(selectFields)) {
            //先过滤一下显示字段，如果在配置表里没有则去除
            List<String> fieldNameList = titleList.stream().map(ReportField::getFieldName).collect(Collectors.toList());
            String[] selectFieldStrings = selectFields.split(",");
            for (String selectField : selectFieldStrings) {
                if (fieldNameList.contains(selectField)) {
                    newSelectFields = StringUtil.StringAdd(newSelectFields, selectField, ", ");
                }
            }
        } else {
            //此时查找用户配置的显示字段
            if (reportUserFieldList.size() > 0) {
                //循环表头
                for (ReportField reportField : titleList) {
                    ReportUserField reportUserField = new ReportUserField();
                    reportUserField.setReportConfigId(reportField.getReportConfigId());
                    reportUserField.setUserId(0);
                    reportUserField.setFieldName(reportField.getFieldName());

                    //如果在用户配置字段里包含该表头，则将用户设置的长度进行赋值
                    if (reportUserFieldList.contains(reportUserField)) {
                        ReportUserField newReportUserField = reportUserFieldList.get(reportUserFieldList.indexOf(reportUserField));
                        reportField.setFieldWidth(newReportUserField.getFieldWidth());
                        newReportFieldList.add(reportField);
                    }
                }

                //显示列为用户设置的列
                newSelectFields = StringUtil.listToString(reportUserFieldList.stream().map(ReportUserField::getFieldName).collect(Collectors.toList()));
            }
        }

        //处理汇总字段，在网格显示中有汇总时需要处理
        String newGroupFields = "";
        if (StringUtil.isNotEmpty(groupFields)) {
            //先记录 groupFields，跟在 group by 语句之后
            groupBySql = groupFields;
            for (ReportField reportField : titleList) {
                String fieldName = reportField.getFieldName();

                if (groupFields.contains(fieldName)) {
                    //汇总对象里包含
                    newGroupFields = StringUtil.StringAdd(newGroupFields, fieldName, ", ");
                    newReportFieldList.add(reportField);
                } else {
                    //汇总对象里不包含的
                    //只要是 integer 的需要合计的，全部进行汇总
                    if (reportField.getFieldType().equals(LbConstant.EXCEL_FIELD_TYPE.INTEGER.getName()) && reportField.getNeedTotal().equals(LbConstant.CONFIRM_1)) {
                        //拼接成 SUM(COALESCE(quantity, 0)) AS quantity, SUM(COALESCE(amount, 0)) AS amount
                        fieldName = "SUM(COALESCE(" + fieldName + ", 0)) as " + fieldName;
                        newGroupFields = StringUtil.StringAdd(newGroupFields, fieldName, ", ");
                        newReportFieldList.add(reportField);
                    }
                }
            }
        }

        //如果用户没有配置标题列，那么直接将以前的标题列返回
        if (newReportFieldList.size() == 0) {
            newReportFieldList.addAll(titleList);
        }

        List<LbMap> newList = new ArrayList<>();
        List<LbMap> sumList = new ArrayList<>();
        long total = 0;
        if (!needSum) {
            //是否分页，默认为true
            boolean havePage = true;
            if (page == 0 && limit == 0) {
                //当page和limit都为0时不分页，用于EXCEL导出
                havePage = false;
            }

            if (havePage) {
                PageHelper.startPage(page, limit);
                List<LbMap> reportList = getNewReportList(selectSql, fromSql, whereSql, groupBySql, orderBySql, newSelectFields, newGroupFields, lastSql);
                PageInfo<LbMap> pageInfo = new PageInfo<>(reportList);
                newList = pageInfo.getList();
                total = pageInfo.getTotal();
            } else {
                newList = getNewReportList(selectSql, fromSql, whereSql, groupBySql, orderBySql, newSelectFields, newGroupFields, lastSql);
                total = newList.size();
            }

            //检查是否有跨单位查询，一定不能有，平台级的报表还是单独写吧
            boolean isEmpty = false;
            if (newList.size() > 0) {
                //取一把，有可能list里包含一个null，会导致后面空指针
                LbMap get0 = newList.get(0);
                if (Objects.isNull(get0)) {
                    isEmpty = true;
                } else {
                    int checkUnitId = newList.get(0).getInt("unitId");
                    for (LbMap map : newList) {
                        if (checkUnitId != map.getInt("unitId")) {
                            throw new BusinessException("不能跨单位进行查询");
                        }
                    }
                }
            } else {
                isEmpty = true;
            }

            //处理合计
            if (!isEmpty) {
                for (ReportField reportField : titleList) {
                    //如果在用户配置字段里包含该表头，不用合计
                    if (reportUserFieldList.size() > 0) {
                        ReportUserField reportUserField = new ReportUserField();
                        reportUserField.setReportConfigId(reportField.getReportConfigId());
                        reportUserField.setUserId(0);
                        reportUserField.setFieldName(reportField.getFieldName());

                        if (!reportUserFieldList.contains(reportUserField)) {
                            continue;
                        }
                    }

                    Integer needTotal = reportField.getNeedTotal();
                    if (IntegerUtil.isEmpty(needTotal)) {
                        needTotal = 0;
                    }

                    //需要合计
                    if (needTotal == 1) {
                        if (!LbConstant.EXCEL_FIELD_TYPE.INTEGER.getName().equals(reportField.getFieldType())) {
                            continue;
                        }

                        String fieldName = reportField.getFieldName();
                        double sumNum = DoubleUtil.round(newList.stream().mapToDouble(x -> x.getDouble(fieldName)).sum());
                        LbMap sumMap = new LbMap();
                        sumMap.put(fieldName, sumNum);
                        sumList.add(sumMap);
                    }
                }
            }
        } else {
            //本次查询是合计
            String fieldName = "";
            for (ReportField reportField : titleList) {
                Integer needTotal = reportField.getNeedTotal();
                if (IntegerUtil.isEmpty(needTotal)) {
                    needTotal = 0;
                }

                if (needTotal == 1) {
                    if (!reportField.getFieldType().equals(LbConstant.EXCEL_FIELD_TYPE.INTEGER.getName())) {
                        continue;
                    }

                    //拼接语句为 ROUND(SUM(COALESCE(pod.box_amount, 0)), 4) AS box_amount
                    fieldName = StringUtil.StringAdd(fieldName, " ROUND(SUM(COALESCE(" + reportField.getAliasFieldName() + ", 0)), 4) AS " + reportField.getFieldName() + " ", ", ");
                }
            }

            if (StringUtil.isNotEmpty(fieldName)) {
                newList = getNewReportList(fieldName, fromSql, whereSql, "", "", "", "", "");
                total = newList.size();
            }
        }

        LbMap resultMap = new LbMap();
        resultMap.put(LbConstant.DATA_LIST, newList);
        resultMap.put(LbConstant.DATA_COUNT, total);
        resultMap.put(LbConstant.TITLE_LIST, newReportFieldList);
        resultMap.put(LbConstant.SUM_LIST, sumList);
        return resultMap;
    }

    /**
     * 动态报表查询（不查总合计）
     *
     * @param param
     * @param moduleId
     * @param detailReportConfigId
     * @param page
     * @param limit
     * @param selectFields
     * @param orderFields
     * @param groupFields
     * @param lastSql
     * @return
     */
    @Override
    @SneakyThrows
    public LbMap getReportList(LbMap param, int moduleId, int detailReportConfigId, int page, int limit, String selectFields, String orderFields, String groupFields, String lastSql) {
        return getReportList(param, moduleId, detailReportConfigId, page, limit, false, selectFields, orderFields, groupFields, lastSql);
    }

    /**
     * 返回查询结果，如果是有 selectFields 则在语句外包裹临时表，如果没有，则不包裹临时表
     *
     * @param selectSql
     * @param fromSql
     * @param whereSql
     * @param groupBySql
     * @param orderBySql
     * @param selectFields
     * @param groupFields
     * @param lastSql
     * @return
     */
    @SneakyThrows
    private List<LbMap> getNewReportList(String selectSql, String fromSql, String whereSql, String groupBySql, String orderBySql, String selectFields, String groupFields, String lastSql) {
        if (StringUtil.isNotEmpty(groupFields) || StringUtil.isNotEmpty(selectFields)) {
            return reportConfigDao.getTempReportList(selectSql, fromSql, whereSql, groupBySql, orderBySql, selectFields, groupFields, lastSql);
        } else {
            return reportConfigDao.getReportList(selectSql, fromSql, whereSql, groupBySql, orderBySql, lastSql);
        }
    }

    /**
     * 报表导出EXCEL
     *
     * @param reportMap
     * @return
     */
    @Override
    @SneakyThrows
    public XSSFWorkbook reportToExcel(LbMap reportMap) {
        List<LbMap> dataList = reportMap.getList(LbConstant.DATA_LIST);
        List<LbMap> titles = reportMap.getList(LbConstant.TITLE_LIST);
        List<List<Object>> list = new ArrayList<>();

        List<String> titleList = new ArrayList<>();
        List<Integer> titleWidth = new ArrayList<>();

        //转数据
        for (LbMap map : dataList) {
            //处理每一行数据
            List<Object> objectList = new ArrayList<>();

            for (Map.Entry<String, Object> hxMapEntry : map.entrySet()) {
                String key = hxMapEntry.getKey();
                Object val = hxMapEntry.getValue();

                for (LbMap title : titles) {
                    String fieldName = title.getString("fieldName");
                    //String newField = LbMap.underlineToCamel(fieldName);
                    String fieldCnName = title.getString("fieldCnName");
                    int fieldWidth = title.getInt("fieldWidth");

                    if (fieldName.equals(key)) {
                        if (!titleList.contains(fieldCnName)) {
                            titleList.add(fieldCnName);
                            titleWidth.add(fieldWidth);
                        }
                        objectList.add(val);
                    }
                }
            }

            list.add(objectList);
        }

        return ExcelUtil.reportToExcel(list, titleList, titleWidth, reportMap.getString(LbConstant.FILE_NAME));
    }

    /**
     * 获取图形报表坐标轴
     *
     * @param moduleId
     * @return
     */
    @Override
    @SneakyThrows
    public LbMap getReportAxis(Integer moduleId) {
        LbMap map = new LbMap();
        ReportConfig reportConfig = getReportConfig(moduleId);
        if (IntegerUtil.isEmpty(reportConfig.getNeedChart())) {
            //throw new BusinessException("[" + reportConfig.getModuleName() + "]报表不支持图形显示");
            return map;
        }

        List<ReportField> reportFieldDictList = reportFieldService.list(new QueryWrapper<ReportField>()
                .eq("report_config_id", reportConfig.getReportConfigId()).orderByAsc("axis"));

        if (reportFieldDictList.size() == 0) {
            throw new BusinessException("[" + reportConfig.getModuleName() + "]报表没有配置坐标轴");
        }


        List<LbMap> xList = new ArrayList<>();
        List<LbMap> yList = new ArrayList<>();
        //List<LbMap> zList = new ArrayList<>();

        for (ReportField reportField : reportFieldDictList) {
            LbMap axisMap = new LbMap();
            axisMap.put("fieldName", reportField.getFieldName());
            axisMap.put("fieldCnName", reportField.getFieldCnName());

            if (StringUtil.isEmpty(reportField.getAxis())) {
                continue;
            }

            if (reportField.getAxis().contains(LbConstant.AXIS_X)) {
                //x轴
                xList.add(axisMap);
            }

            if (reportField.getAxis().contains(LbConstant.AXIS_Y)) {
                //y轴
                yList.add(axisMap);
            }

            /*if (reportField.getAxis().contains(LbConstant.AXIS_Z)) {
                //z轴
                zList.add(axisMap);
            }*/
        }

        map.put("xList", xList);
        map.put("yList", yList);
        //map.put("zList", zList);
        return map;
    }

    /**
     * 获取图形报表数据
     *
     * @param oriList
     * @param xParam
     * @param yParam
     * @param zParam
     * @param param
     * @return
     */
    @Override
    @SneakyThrows
    public LbMap getReportAxisList(List<LbMap> oriList, String xParam, String yParam, String zParam, LbMap param) {
        LbMap resultMap = new LbMap();

        List<LbMap> dataList = new ArrayList<>();
        LbMap sumMap = new LbMap();

        if (oriList.size() == 0) {
            resultMap.put("dataList", dataList);
            resultMap.put("sumMap", sumMap);
            return resultMap;
        }

        List<LbMap> newList = new ArrayList<>();
        double sumValue = 0.0d;
        Map<String, List<LbMap>> xMap = oriList.stream().collect(Collectors.groupingBy(x -> x.getString(xParam)));
        for (Map.Entry<String, List<LbMap>> xEntry : xMap.entrySet()) {
            String xName = xEntry.getKey();

            List<LbMap> yList = xEntry.getValue();
            double yValue = DoubleUtil.round(yList.stream().mapToDouble(y -> y.getDouble(yParam)).sum());

            LbMap newMap = new LbMap();
            newMap.put("x", xName);
            newMap.put("y", yValue);
            newList.add(newMap);
            sumValue += yValue;
        }

        //如果需要合计，则把合计内容返回
        if (param.getInt("needTotal") == 1) {
            int moduleId = param.getInt("moduleId");
            ReportConfig reportConfig = getReportConfig(moduleId);
            Integer reportConfigId = reportConfig.getReportConfigId();
            QueryWrapper<ReportField> fieldWrapper = new QueryWrapper<>();
            fieldWrapper.eq("report_config_id", reportConfigId)
                    .eq("on_show", LbConstant.ON_SHOW.SHOW.getCode())
                    .eq("field_name", yParam)
                    .orderByAsc("order_by");
            List<ReportField> titleList = reportFieldService.list(fieldWrapper);
            if (titleList.size() > 0) {
                ReportField reportField = titleList.get(0);
                sumMap.put(reportField.getFieldCnName(), sumValue);
            }
        }

        if (param.getInt(LbConstant.RANKING_FIELD) == 1) {
            //这里需要获取所有列表里的倒序，保证金额大的值排在最前面
            List<LbMap> sortList = newList.stream().sorted(Comparator.comparing(this::getDouble).reversed()).collect(Collectors.toList());
            if (sortList.size() >= param.getInt(LbConstant.RANKING_COUNT_FIELD)) {
                dataList = sortList.subList(0, param.getInt(LbConstant.RANKING_COUNT_FIELD));
            } else {
                dataList = sortList;
            }

            //这里获取了前10名了，然后正序返给前端，因为前端是从最后一个最大金额开始渲染
            dataList = dataList.stream().sorted(Comparator.comparing(this::getDouble)).collect(Collectors.toList());
        } else {
            dataList = newList.stream().sorted(Comparator.comparing(x -> x.getString("x"))).collect(Collectors.toList());
        }

        resultMap.put("dataList", dataList);
        resultMap.put("sumMap", sumMap);
        return resultMap;
    }

    /**
     * 获取看板配置
     *
     * @param moduleId
     * @return
     */
    @Override
    @SneakyThrows
    public List<ReportChart> getReportChart(Integer moduleId) {
        QueryWrapper<ReportChart> wrapper = new QueryWrapper<>();
        if (IntegerUtil.isNotEmpty(moduleId)) {
            wrapper.eq("module_id", moduleId);
        }
        List<ReportChart> list = reportChartService.list(wrapper);
        list.forEach(x -> x.setHaveDate((StringUtil.isEmpty(x.getDateFieldName())) ? 0 : 1));
        return list;
    }

    /**
     * 获取看板列表的条件下拉内容
     *
     * @param moduleId
     * @return
     */
    @Override
    @SneakyThrows
    public LbMap getReportChartWhere(Integer moduleId) {
        List<ReportChartWhere> reportChartWhereList = reportChartWhereService.list(new QueryWrapper<ReportChartWhere>().eq("module_id", moduleId));
        LbMap resultMap = new LbMap();

        List<LbMap> whereList = new ArrayList<>();
        for (ReportChartWhere reportWhere : reportChartWhereList) {
            LbMap whereMap = new LbMap();
            whereMap.put("paramName", reportWhere.getParamName());
            whereMap.put("paramType", reportWhere.getParamType());
            whereMap.put("fieldName", reportWhere.getFieldName());
            whereMap.put("fieldCnName", reportWhere.getFieldCnName());
            whereMap.put("defaultValue", reportWhere.getDefaultValue());
            whereList.add(whereMap);
        }
        resultMap.put("reportChartWhereList", whereList);

        if (reportChartWhereList.size() == 0) {
            return resultMap;
        }

        for (ReportChartWhere reportWhere : reportChartWhereList) {
            if (reportWhere.getParamType().equals(LbConstant.PARAM_TYPE.SELECT.getName())) {
                if (StringUtil.isEmpty(reportWhere.getTableName())) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 select 时，表名称不能为空");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                if (StringUtil.isEmpty(reportWhere.getLinkJson())) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 select 时，关联json不能为空");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                Map<String, String> keyMap = new HashMap<>();
                try {
                    keyMap = JSONObject.parseObject(reportWhere.getLinkJson(), Map.class);
                } catch (Exception e) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 select 时，关联json解析不成功");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                String key = "";
                String value = "";

                if (Objects.isNull(keyMap)) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 select 时，关联json解析为空");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                for (Map.Entry<String, String> entry : keyMap.entrySet()) {
                    key = entry.getKey();
                    value = entry.getValue();

                    if (StringUtil.isNotEmpty(key) && StringUtil.isNotEmpty(value)) {
                        break;
                    }
                }

                //select 类型的字段，需要把下拉的值返回，以 [{"id":1, "name":张三}] 的json 格式返回
                List<LbMap> selectList = reportConfigDao.getSelectList(reportWhere.getTableName(), 0, key, value);
                resultMap.put(reportWhere.getParamName(), selectList);
            } else if (reportWhere.getParamType().equals(LbConstant.PARAM_TYPE.LIST.getName())) {
                if (StringUtil.isEmpty(reportWhere.getLinkJson())) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 list 时，关联json不能为空");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }

                List<LbMap> selectList = new ArrayList<>();
                try {
                    selectList = JSONObject.parseObject(reportWhere.getLinkJson(), List.class);
                } catch (Exception e) {
                    log.info(reportWhere.getFieldName() + " 参数类型为 list 时，关联json解析不成功");
                    throw new BusinessException("报表配置有误，请联系系统管理员");
                }
                resultMap.put(reportWhere.getParamName(), selectList);
            }
        }

        return resultMap;
    }

    /**
     * 分页查询列表
     *
     * @param page  页数
     * @param limit 条数
     * @param param 参数
     * @return PageInfo 分页列表
     */
    @Override
    public PageInfo<ReportConfig> getList(int page, int limit, LbMap param) {
        QueryWrapper<ReportConfig> wrapper = new QueryWrapper<>();
        PageHelper.startPage(page, limit);
        List<ReportConfig> list = reportConfigDao.selectList(wrapper);
        return new PageInfo<ReportConfig>(list);
    }

    /**
     * 查询所有列表
     *
     * @param param 参数
     * @return list 全部列表
     */
    @Override
    public List<ReportConfig> getAllList(LbMap param) {
        QueryWrapper<ReportConfig> wrapper = new QueryWrapper<>();
        return reportConfigDao.selectList(wrapper);
    }

    /**
     * 通过编号查询
     *
     * @param primaryKey
     * @return 报表配置
     */
    @Override
    @SneakyThrows
    public ReportConfig getById(String primaryKey) {
        ReportConfig reportConfig = reportConfigDao.selectById(primaryKey);
        if (Objects.isNull(reportConfig)) {
            throw new BusinessException("报表配置编号不正确");
        }
        return reportConfig;
    }

    /**
     * 新增信息
     *
     * @param reportConfig reportConfig
     */
    @Override
    @SneakyThrows
    public void saveOne(ReportConfig reportConfig) {
        int count = reportConfigDao.insert(reportConfig);
        if (count != 1) {
            throw new BusinessException("报表配置保存失败");
        }

        List<ReportField> reportFieldList = reportConfig.getReportFieldList();
        if (Objects.nonNull(reportFieldList) && reportFieldList.size() > 0) {
            for (ReportField reportField : reportFieldList) {
                reportField.setReportConfigId(reportConfig.getReportConfigId());
                reportFieldService.saveOne(reportField);
            }
        }

        List<ReportWhere> reportWhereList = reportConfig.getReportWhereList();
        if (Objects.nonNull(reportWhereList) && reportWhereList.size() > 0) {
            for (ReportWhere reportWhere : reportWhereList) {
                reportWhere.setReportConfigId(reportConfig.getReportConfigId());
                reportWhereService.saveOne(reportWhere);
            }
        }
    }

    /**
     * 更新信息
     *
     * @param reportConfig reportConfig
     */
    @Override
    @SneakyThrows
    public void update(ReportConfig reportConfig) {
        int count = reportConfigDao.updateById(reportConfig);
        if (count != 1) {
            throw new BusinessException("报表配置更新失败");
        }

        List<ReportField> reportFieldList = reportConfig.getReportFieldList();
        if (Objects.nonNull(reportFieldList) && reportFieldList.size() > 0) {
            for (ReportField reportField : reportFieldList) {
                reportFieldService.update(reportField);
            }
        }

        List<ReportWhere> reportWhereList = reportConfig.getReportWhereList();
        if (Objects.nonNull(reportWhereList) && reportWhereList.size() > 0) {
            for (ReportWhere reportWhere : reportWhereList) {
                reportWhereService.update(reportWhere);
            }
        }
    }

    /**
     * 删除信息
     *
     * @param primaryKey id
     */
    @Override
    @SneakyThrows
    public void delete(String primaryKey) {
        ReportConfig reportConfig = reportConfigDao.selectById(primaryKey);
        if (Objects.isNull(reportConfig)) {
            throw new BusinessException("未通过编号找到报表配置");
        }
        int count = reportConfigDao.deleteById(primaryKey);
        if (count != 1) {
            throw new BusinessException("报表配置删除失败");
        }

        boolean remove = reportWhereService.remove(new QueryWrapper<ReportWhere>().eq("report_config_id", primaryKey));
        if (!remove) {
            throw new BusinessException("报表条件删除失败");
        }

        remove = reportFieldService.remove(new QueryWrapper<ReportField>().eq("report_config_id", primaryKey));
        if (!remove) {
            throw new BusinessException("报表字段删除失败");
        }
    }

    private Double getDouble(LbMap map) {
        return map.getDouble("y");
    }

    /**
     * 通过模块编号查找报表配置
     *
     * @param moduleId
     * @return
     */
    @SneakyThrows
    private ReportConfig getReportConfig(Integer moduleId) {
        QueryWrapper<ReportConfig> reportWrapper = new QueryWrapper<>();
        reportWrapper.eq("module_id", moduleId);
        List<ReportConfig> reportConfigList = this.list(reportWrapper);
        if (reportConfigList.size() <= 0) {
            throw new BusinessException("没有找到对应的报表设置");
        }
        //找到报表设置
        return reportConfigList.get(0);
    }

    /**
     * 获取参数名称，然后替换 whereSql
     *
     * @return
     */
    private String getParamName() {
        return LbConstant.LEFT_REPLACE + "unitId" + LbConstant.RIGHT_REPLACE;
    }

    /**
     * 获取参数名称，然后替换 dataPurview
     *
     * @return
     */
    private String getParamUserName() {
        return LbConstant.LEFT_REPLACE + "userName" + LbConstant.RIGHT_REPLACE;
    }

    /**
     * 获取报表标题、条件、用户自定义标题等信息
     *
     * @param reportConfigId
     * @param whereOnShow    是否显示所有查询条件，看板跳转时，需要显示所有查询条件（包含 tb_report_where.on_show = 0 的数据）
     * @return
     */
    @Override
    public ReportConfig getReportInfo(Integer reportConfigId, boolean whereOnShow) {
        ReportConfig reportConfig = new ReportConfig();
        //这里可以优化成通过 redis 取各个列表以加快访问速度，现在没有配置页面，不能保证 redis 与数据库同步，所以先不写

        QueryWrapper<ReportField> fieldWrapper = new QueryWrapper<>();
        fieldWrapper.eq("report_config_id", reportConfigId).eq("on_show", LbConstant.ON_SHOW.SHOW.getCode()).orderByAsc("order_by");
        List<ReportField> titleList = reportFieldService.list(fieldWrapper);
        reportConfig.setReportFieldList(titleList);

        //查询条件
        QueryWrapper<ReportWhere> whereWrapper = new QueryWrapper<>();
        whereWrapper.eq("report_config_id", reportConfigId).orderByAsc("order_by");
        if (whereOnShow) {
            whereWrapper.eq("on_show", LbConstant.ON_SHOW.SHOW.getCode());
        }
        List<ReportWhere> whereParamList = reportWhereService.list(whereWrapper);
        reportConfig.setReportWhereList(whereParamList);

        //用户显示列标题
        QueryWrapper<ReportUserField> userFieldWrapper = new QueryWrapper<>();
        userFieldWrapper.eq("report_config_id", reportConfigId).eq("user_id", 0).orderByAsc("order_by");
        List<ReportUserField> reportUserFieldList = reportUserFieldService.list(userFieldWrapper);
        reportConfig.setReportUserFieldList(reportUserFieldList);

        return reportConfig;
    }

    /**
     * 比较
     *
     * @param compare    比较
     * @param paramName  参数名
     * @param paramValue 参数值
     * @return
     */
    @SneakyThrows
    private String getCompare(int compare, String paramName, String paramValue) {
        if (compare == LbConstant.COMPARE.EQ.getCode()) {
            //连接符是等于
            return paramName + " = '" + paramValue + "' ";
        } else if (compare == LbConstant.COMPARE.GT.getCode()) {
            //连接符是大于
            return paramName + " > '" + paramValue + "' ";
        } else if (compare == LbConstant.COMPARE.GE.getCode()) {
            //连接符是大于等于
            return paramName + " >= '" + paramValue + "' ";
        } else if (compare == LbConstant.COMPARE.LT.getCode()) {
            //连接符是小于
            return paramName + " < '" + paramValue + "' ";
        } else if (compare == LbConstant.COMPARE.LE.getCode()) {
            //连接符是小于等于
            return paramName + " <= '" + paramValue + "' ";
        } else if (compare == LbConstant.COMPARE.LIKE.getCode()) {
            return paramName + " like '%" + paramValue + "%' ";
        } else if (compare == LbConstant.COMPARE.IN.getCode()) {
            return paramName + " in (" + paramValue + ") ";
        }

        throw new BusinessException("比较参数设置不正确");
    }
}
